﻿function recDomain(element, parentTag) {
    var html = "<ul>";
    for (var i = 0; i < element.length; i++) {
        var relation = "";
        if (element[i].RelationType() == "one" || element[i].RelationType() == "One") {
            relation = element[i].DomainTypesChild().ObjName();
        } else {
            relation = element[i].RelationType() + " " + element[i].DomainTypesChild().ObjName();
        }
        html += "<li>" + element[i].AccMod() + " " + relation + " " + element[i].PropertyName();
        html = recDomain(element[i].DomainTypesChild().Parent(), html);
        html += ("</li>");
    }
    html += "</ul>";
    parentTag += html;
    return parentTag;
}
function recApp(element, parentTag) {
    var html = "<ul>";
    for (var i = 0; i < element.length; i++) {
        var relation = "";
        if (element[i].RelationType() == "one" || element[i].RelationType() == "One") {
            relation = element[i].AppTypesChild().ObjName();
        } else {
            relation = element[i].RelationType() + " " + element[i].AppTypesChild().ObjName();
        }
        html += "<li>" + element[i].AccMod() + " " + relation + " " + element[i].PropertyName();
        html = recApp(element[i].AppTypesChild().Parent(), html);
        html += "</li>";
    }
    html += "</ul>";
    parentTag += html;
    return parentTag;
}
function layoutDomain(element, parentTag) {
    var html = "<ul style='margin:0'>";
    html += element.ObjName();
    for (var i = 0; i < element.Parent().length; i++) {
        var relation = "";
        if (element.Parent()[i].RelationType() == "one" || element.Parent()[i].RelationType() == "One") {
            relation = element.Parent()[i].DomainTypesChild().ObjName();
        } else {
            relation = element.Parent()[i].RelationType() + " " + element.Parent()[i].DomainTypesChild().ObjName();
        }
        html += "<li>" + element.Parent()[i].AccMod() + " " + relation + " " + element.Parent()[i].PropertyName();
        html = recDomain(element.Parent()[i].DomainTypesChild().Parent(), html);
        html += "</li>";
    }
    html += "</ul>";
    parentTag.html(html);
    return parentTag;
}
function layoutApp(element, parentTag) {
    var html = "<ul style='margin:0'>";
    html += element.ObjName();
    for (var i = 0; i < element.OutsideRelationships().length; i++) {
        var relation = "";
        if (element.OutsideRelationships()[i].RelationType() == "one" || element.OutsideRelationships()[i].RelationType() == "One") {
            relation = element.OutsideRelationships()[i].DomainTypes().ObjName();
        } else {
            relation = element.OutsideRelationships()[i].RelationType() + " " + element.OutsideRelationships()[i].DomainTypes().ObjName();
        }
        html += "<li>" + element.OutsideRelationships()[i].AccMod() + " " + relation + " " + element.OutsideRelationships()[i].PropertyName();
        html = recDomain(element.OutsideRelationships()[i].DomainTypes().Parent(), html);
        html += "</li>";
    }

    for (var i = 0; i < element.Parent().length; i++) {
        var relation = "";
        if (element.Parent()[i].RelationType() == "one" || element.Parent()[i].RelationType() == "One") {
            relation = element.Parent()[i].AppTypesChild().ObjName();
        } else {
            relation = element.Parent()[i].RelationType() + " " + element.Parent()[i].AppTypesChild().ObjName();
        }
        html += "<li>" + element.Parent()[i].AccMod() + " " + relation + " " + element.Parent()[i].PropertyName();
        html = recApp(element.Parent()[i].AppTypesChild().Parent(), html);
        html += "</li>";
    }
    html += "</ul>";
    parentTag.html(html);
    return parentTag;
}
function addDomObject(newType, _propType, _propName, relation, accessModify) {
    //Bug: can't autogenerated keys for entities with multipart keys
    //Walkaround: manual create GUID key
    var newDomain = manager.createEntity("OutsideRelation", { UniqueId: breeze.core.getUuid(), AppTypes: newType, DomainId: _propType, PropertyName: _propName, RelationType: relation, AccMod: accessModify });
    manager.addEntity(newDomain);
}
function addAppObject(newType, _propType, _propName, relation, accessModify) {
    //Bug: can't autogenerated keys for entities with multipart keys
    //Walkaround: manual create GUID key
    var newApp = manager.createEntity("AppRelation", { UniqueId: breeze.core.getUuid(), AppTypesPar: newType, AppChildId: _propType, PropertyName: _propName, RelationType: relation, AccMod: accessModify });
    manager.addEntity(newApp);
}

function renderTable(element) {
    var html = "<div class='input-group pull-left myinput'><input data-bind='value: ObjName' class='form-control' type='text' placeholder='Type name' /></div>";
    html += "<table style='clear:both;'>";
    html += "<tr><th>Attribute</th><th>Access Modify</th><th>Relation</th><th>Property Type</th><th>Property Name</th></tr>";
    html += "<tbody data-bind='foreach: selection'><tr>";
    html += "<td><select class='form-control'><option value='None'>None</option><option value='Key'>Key</option><option value='FK'>Foreign Key</option></select></td>";
    html += "<td><select data-bind='value: AccMod' class='form-control'><option value='Public'>Public</option><option value='Private'>Private</option><option value='Protected'>Protected</option></select></td>";
    html += "<td><select data-bind='value: RelationType' class='form-control'><option value='One'>One</option><option value='ICollection'>ICollection</option></select></td>";
    html += "<td>";

    //If $data is Domain Types
    html += "<!-- ko if: $data.DomainId -->";
    html += "<select class='form-control' data-bind='";
    html += "options: $root.AllTypes, ";
    html += 'optionsText: "ObjName",';
    //html += 'optionsValue: "UniqueId",';
    html += 'value: DomainTypes ,';
    html += "";
    html += 'optionsCaption: "Choose..."';
    html += "'></select>";
    html += "<!-- /ko -->";
    //If $data is Application Types
    html += "<!-- ko if: $data.AppChildId -->";
    html += "<select class='form-control' data-bind='";
    html += "options: $root.AllTypes, ";
    html += 'optionsText: "ObjName",';
    //html += 'optionsValue: "UniqueId",';
    html += 'value: AppTypesChild ,';
    //html += 'value: AppChildId ,';
    html += 'optionsCaption: "Choose..."';
    html += "'></select>";
    html += "<!-- /ko -->";

    //html += "<input type='text' data-bind='value: $data.PropertyName' />";

    html += "</td>";
    html += "<td><div class='input-group pull-left myinput'><input data-bind='value: PropertyName' class='form-control' type='text' placeholder='Property Name' /></div>";
    html += "<button class='btn btn-xs btn-default' onclick=''><span class='glyphicon glyphicon-plus'></span></button>";
    html += "<button class='btn btn-xs btn-default' onclick=''><span class='glyphicon glyphicon-minus'></span></button>";
    html += "</td>";
    html += "</tr></tbody>";

    html+="</table>";
    $('#editArea').html(html);
    element.AllTypes = vm.AllTypes;
    element.selection = ko.observableArray();
    for (var i = 0; i < element.OutsideRelationships().length; i++) {
        element.selection.push(element.OutsideRelationships()[i]);
    }
    for (var i = 0; i < element.Parent().length; i++){
        element.selection.push(element.Parent()[i]);
    }

    vm.special = element.OutsideRelationships()[0];
    vm.data = element.selection()[0];
    element.selection.subscribe(function (data) {
        var s = "";
        alert('changes detected');
    });

    //element.special = element.Parent()[0].AppTypesChild();
    ko.cleanNode($('#editAreaParent')[0]);
    ko.applyBindings(element, $('#editAreaParent')[0]);
    
    
}
function refreshStructure() {
    var element = ko.dataFor($('#editArea')[0]);
    if (!(typeof element === "undefined")) {
        layoutApp(element, $('#structureView'));
    }
}

$(function () {
    vm.clickAppTypes = function (element) {
        //Render structure
        layoutApp(element, $('#structureView'));

        //Render to edit
        element.saveEntity = function (data) {
            // Maybe a bug: only save single entity but can't save its children
            // manager.saveChanges([data]).then(saveSucceeded).fail(saveFailed); <--- can't use this
            // More info: http://stackoverflow.com/questions/13575058/how-can-i-save-a-single-entity-with-entitymanagers-savechanges-method            
            //Solution to walk around:
            var entitiesToSave = Array();

            if (data.Parent().length > 0) {
                for (var i = 0; i < data.Parent().length ; i++) {
                    entitiesToSave.push(data.Parent()[i]);
                }
            }
            if (data.OutsideRelationships().length > 0) {
                for (var i = 0; i < data.OutsideRelationships().length ; i++) {
                    entitiesToSave.push(data.OutsideRelationships()[i]);
                }
            }
            // Limitation: can not modify key/part of key in Breeze
            // Solution to walk around: modify manual on both server and client consistently
            for (var i = 0; i < entitiesToSave.length; i++){
                var originalValues = entitiesToSave[i].entityAspect.originalValues;
                var newVal = Array();
                var newKeyval = '';
                var hasChangedKey = false;
                jQuery.each(originalValues, function (name, value) {
                    //Check if Guid --> Key
                    if(value.match(/^[{]?[0-9a-fA-F]{8}[-]?([0-9a-fA-F]{4}[-]?){3}[0-9a-fA-F]{12}[}]?$/)){
                        newKeyval = entitiesToSave[i].getProperty(name);
                        hasChangedKey = true;
                    } else {
                        // If property is not key, save it temporary
                        var obj = new Object;
                        obj.name = name;
                        obj.val = entitiesToSave[i].getProperty(name);
                        newVal.push(obj);
                    }
                });
                entitiesToSave[i].entityAspect.rejectChanges();
                for (var j = 0; j < newVal.length; j++){
                    entitiesToSave[i].setProperty(newVal[j].name, newVal[j].val);                    
                }
                manager.saveChanges([entitiesToSave[i]]).then(saveSucceeded).fail(saveFailed);
                               
                if (hasChangedKey) {
                    //Change key on server
                    changeKeyonServer(entitiesToSave[i].entityAspect, newKeyval);

                    //Change key on client
                    changeKeyonClient(entitiesToSave[i].entityAspect, newKeyval);
                }
                
            }    
        };
        element.rejectChanges = function (data) {
            for (var i = 0; i < data.Parent().length ; i++) {
                data.Parent()[i].entityAspect.rejectChanges();
            }
            data.entityAspect.rejectChanges();
        };

        renderTable(element);
    };

    vm.clickDomTypes = function (element) {
        //Render structure
        layoutDomain(element, $('#structureView'));

        //Render to edit
        $('#editArea').html("<i>You're not allowed to edit this type</i>");
    };
});
function changeKeyonServer(entityAspect, newKey) {

    var saveq = breeze.EntityQuery.from('SaveModifiedKey').withParameters(
                    {
                        KeyName1: entityAspect._entityKey.entityType.dataProperties[0].name,
                        KeyVal1: entityAspect._entityKey.values[0],
                        KeyName2: entityAspect._entityKey.entityType.dataProperties[1].name,
                        KeyVal2: entityAspect._entityKey.values[1],
                        KeyName3: entityAspect._entityKey.entityType.dataProperties[2].name,
                        KeyVal3: entityAspect._entityKey.values[2],
                        TypeName: entityAspect.entityGroup.entityType.shortName,
                        newKey3: newKey
                    });
    manager.executeQuery(saveq);
}
function changeKeyonClient(entityAspect, newkey) {
    var keySplit = entityAspect._entityKey._keyInGroup.split(':::');
    entityAspect._entityKey._keyInGroup = keySplit[0] + ":::" + keySplit[1] + ":::" + newkey
    entityAspect._entityKey.values[2] = newkey;
    entityAspect.setUnchanged();
}

function initUI() {
    $(".draggable").draggable({
        helper: 'clone',
        cursor: "move"
    });
}
function reBind(ele) {
    var selection = ele.find("#selectType");
    ko.cleanNode($(selection)[0]);
    ko.applyBindings(vm, $(selection)[0]);
}
// Edit type
function _addProp() {

}
function _delProp() {

}


// Create new type
function addType(element) {
    var table = $(element).parent().clone();
    reBind(table);
    $('#collapseTwo > .panel-body').append(table);
}
function delType(element) {
    $(element).parent().remove();
}
function addProp(element) {
    var cloneObj = $(element).parent().parent().clone();
    reBind(cloneObj);
    $(element).parent().parent().parent().append(cloneObj);
}
function delProp(element) {
    $(element).parent().parent().remove();
}
function createType() {
    $('#createStruc div').each(function () {
        var typeName = $(this).find('#typename').val();
        var newType = manager.createEntity("AppTypes", { ObjName: typeName });
        vm.AppTypes.push(newType);
        var tmp = new Object;
        tmp.UniqueId = "DomId" + newType.UniqueId();
        tmp.ObjName = newType.ObjName();
        vm.AllTypes.push(tmp);

        var trlist = $($(this).find('#newType')).find('tbody').children();
        for (var i = 1; i < trlist.length; i++) {
            var accessModify = $(trlist[i].cells[0].children[0]).val();
            var relation = $(trlist[i].cells[1].children[0]).val();
            var _propType = $(trlist[i].cells[2].children[0]).val();
            var _propName = $(trlist[i].cells[3].children[0]).val();
            if (_propType.indexOf("App") == 0) {
                _propType = _propType.substr(5, _propType.length);
                addAppObject(newType, _propType, _propName, relation, accessModify);
            }
            if (_propType.indexOf("Dom") == 0) {
                _propType = _propType.substr(5, _propType.length);
                addDomObject(newType, _propType, _propName, relation, accessModify);
            }
        }
    });
    //Save();
}